home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1993 December
/
PSL Monthly Shareware CD-ROM (December 1993).iso
/
prgmming
/
win
/
pascal
/
dynst.exe
/
DYNST1.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1991-10-18
|
10KB
|
344 lines
UNIT DYNSTR1;
{ ================================================================
DYNSTR1.PAS
Compiler: Turbo Pascal for Windows v. 1
Date: 10/18/91
By: Tom Campbell
What it is: Dynamic string array unit
What it's for: Allocating arrays of strings on the heap, and
handling all memory management transparently.
An interactive demo program shows how to use
this unit. It appears after the last END of
the unit.
Copyright (C) 1991 by Tom Campbell.
You may use this however you wish as long as
you retain the copyright notice in the source
code.
================================================================ }
{ Publicly visible routines & data types. }
INTERFACE
CONST
{ Biggest dynamic variable that can be allocated. Actually, it's not
quite the biggest. I'm leaving slop memory just to be sure. }
MaxArraySize = 64000;
{ Figure out how big the biggest possible array could be. This amount
won't necessarily be allocated, but it's used to fool Pascal into
allowing us to address a dynamically allocated array of any size
from 1 to MaxStrArraySize. }
MaxStrArraySize = MaxArraySize DIV SizeOf(STRING);
TYPE
{ With range checking disabled, this can be used to create a
dynamically sized array of pointers to strings. }
PStrArray = ^TStrArray;
TStrArray = ARRAY[0..MaxStrArraySize - 1] OF STRING;
{ This is a dynamically allocated array of pointers to strings.
LABuffer is short for "look ahead buffer". }
PTLABuffer = ^TLABuffer;
TLABuffer = OBJECT
{ Error code. FALSE if everything's okay, TRUE if error. }
BufError : BOOLEAN;
{ Size of array. }
BufSize : WORD;
{ Current position in array.}
BufIndex : WORD;
{ Address of first element of dynamically allocated array. }
BufStart : PStrArray;
{ Deallocate dynamically allocated members of this
structure. }
DESTRUCTOR Done;
{ Allocate an array. }
{ Return error code: Simply TRUE there's an error, or FALSE
if not. }
FUNCTION Error : BOOLEAN;
CONSTRUCTOR Init(NumElements : WORD);
{ Read string at array position Index and return it. }
FUNCTION ReadElement(VAR Index : WORD) : STRING;
{ Returns # of elements in the dynamically allocated array. }
FUNCTION NumOfElements : WORD;
{ Write a string to position Index. }
PROCEDURE WriteElement(VAR Index : WORD; Element : STRING);
END;
{ Routines in this unit. }
IMPLEMENTATION
DESTRUCTOR TLABuffer.Done;
{==================================================================
What it does:
Returns dynamically allocated fields of this object.
Example:
Dispose(Buf, Done);
==================================================================}
BEGIN
{ Return the dynamically allocated string array. }
FreeMem(BufStart, BufSize * SizeOf(STRING));
END; { PROCEDURE DESTRUCTOR TLABuffer.Done }
FUNCTION TLABuffer.Error: BOOLEAN;
{==================================================================
What it does:
Returns TRUE if an error has occurred, or FALSE if none has
occurred.
Returns:
- TRUE if an error occurred.
- FALSE if not.
Example:
IF Buf^.Error THEN
BEGIN
WriteLn('Unable to allocate a PLABuffer object. Quitting.');
Halt(1);
END;
==================================================================}
BEGIN
{ This isn't a very challenging routine...}
Error := BufError;
END; { FUNCTION TLABuffer.Error }
CONSTRUCTOR TLABuffer.Init(NumElements : WORD);
{==================================================================
What it does:
Allocates an array of BufSize STRING elements. If there isn't
enough memory, sets BufError to a nonzero value. If there is,
sets BufError to FALSE.
Initializes all strings to ''.
Parameters:
- NumElements : The # of elements to be allocated for the string
array.
Example:
New(Buf, Init(10));
==================================================================}
VAR
{ Loop counter/array index. }
EachString : WORD;
BEGIN
{ Assume an error (0 means none). }
BufError := TRUE;
{ Make sure it's not too big. }
IF NumElements < MaxStrArraySize THEN
BufSize := NumElements
ELSE
BEGIN
BufSize := 0;
Exit;
END;
IF MaxAvail < (BufSize * SizeOf(STRING)) THEN
Exit;
{ If there is enough memory, allocate BufSize elements' worth
and point BufStart at that location. }
GetMem(BufStart, BufSize * SizeOf(STRING));
{ Set flag to "no error" if there's enough memory. }
BufError := FALSE;
{ Index starts at 0th element. }
BufIndex := 0;
{ Initialize all strings to null values. }
FOR EachString := 0 TO PRED(BufSize) DO
BufStart^[EachString] := #0;
END; { CONSTRUCTOR TLABuffer.Init }
FUNCTION TLABuffer.NumOfElements : WORD;
{==================================================================
What it does:
Returns the # of elements in the array. This is of course the
same amount it was initialized with, assuming the initialization
was successful.
Returns:
- # of elements in the array (0 if none could be allocated).
Example:
WriteLn('# of elements in array: ', Buf^.NumOfElements);
==================================================================}
BEGIN
NumOfElements := BufSize;
END; { FUNCTION TLABuffer.NumOfElements }
FUNCTION TLABuffer.ReadElement(VAR Index : WORD) : STRING;
{==================================================================
What it does:
Retrieves a string at array index Index, writing it to
the return value. If there's an error--that is, the index is
past the end of the buffer--returns an empty string and sets
BufError to TRUE.
If this were a real string array, this would be the equivalent
of
StrVariable = Buffer[Index];
Parameters:
- Index : Array element to read.
Returns:
- The string at array position Index on success.
- A null string on failure.
Example:
FOR i := 0 TO PRED(Buf^.BufSize) DO
BEGIN
WriteLn(Buf^.ReadElement(i));
END;
==================================================================}
BEGIN
{ See if the requested string is out of bounds. }
IF Index >= BufSize THEN
BEGIN
{ Flag this as an error condition. }
BufError := TRUE;
{ Return a known value. }
ReadElement := '';
{ Exit this routine. }
Exit;
END;
{ Wasn't out of bounds. Return the string at this position. }
ReadElement := BufStart^[Index];
END; { FUNCTION TLABuffer.ReadElement }
PROCEDURE TLABuffer.WriteElement(VAR Index : WORD; Element : STRING);
{==================================================================
What it does:
Writes Element to array position Index. If Index is out of
bounds, does nothing and sets BufError to TRUE.
If this were a real string array, this would be the equivalent
of
Buffer[Index] := Element;
Parameters:
- Index : Array position to write string to.
- Element : String to write into array.
Example:
Write('Please enter string #', i, ': ');
ReadLn(s);
Buf^.WriteElement(i, s);
==================================================================}
BEGIN
{ See if the requested string is out of bounds. }
IF Index >= BufSize THEN
BEGIN
{ Flag this as an error condition. }
BufError := TRUE;
{ Exit this routine. }
Exit;
END;
{ Everything's okay. Write the string in. }
BufStart^[Index] := Element;
END; { PROCEDURE TLABuffer.WriteElement }
END.
End of unit. Any comments can go here.
{ ================================================================
DEMO PROGRAM
Asks for a small array (simply to keep the demo reasonably
short), then has user enter strings into it interactively.
Displays them, th